
	
TransgeneticAlgorithm::TransgeneticAlgorithm( const char* input_file ) : Algorithm( input_file ) {
	//number of individuals
	
	n = 100;
	alpha = 0.5;
	max_plasmideos = n/2;
	
	quality_best = 0;
	
}

TransgeneticAlgorithm::~TransgeneticAlgorithm() {
	for (int i = 0; i < plasmideos.size(); ++i) {
		delete plasmideos[i];
	}
	deletePopulation(population);
}

int TransgeneticAlgorithm::compareIndividuals(const void* i1, const void* i2) {
	return (*((Cromossom**)i2))->assessFitness() - (*((Cromossom**)i1))->assessFitness();
}

void TransgeneticAlgorithm::solve() {
	population = initPopulation();
	
	time_t start = time(NULL);
	do {
		
		generatePlasmideos();
		
		if (rand()%2) {
			applyPlasmideo();
		} else {
			applyTranspossom();
		}
		
		checkBest();
		
	}while((time(NULL) - start < 3));
	
}

void TransgeneticAlgorithm::applyTranspossom() {
	for (int i = 0; i < alpha*n; ++i) {
		population[i]->applyTranspossom();
	}
}

void TransgeneticAlgorithm::applyPlasmideo() {
	for (int i = 0; i < alpha*n; ++i) {
		population[i]->applyPlasmideo(choosePlasmideo());
	}
}

Set* TransgeneticAlgorithm::choosePlasmideo(){
	
	if (plasmideos.size() == 0) {	
		return NULL;
	}
	
	int i = rand()%plasmideos.size();
	return plasmideos[i];
}

void TransgeneticAlgorithm::generatePlasmideos() {
	qsort(population, n, sizeof(Cromossom*), TransgeneticAlgorithm::compareIndividuals);
		
	Set* new_plasmideo = new Set();
	
	new_plasmideo->union_(population[0]->getSolutionAsSet());
	new_plasmideo->intersection(population[1]->getSolutionAsSet());
	
	if (new_plasmideo->cardinality() > 0) {
		if (plasmideos.size() < max_plasmideos) {
			plasmideos.push_back(new_plasmideo);
		} else {
			int i = rand()%plasmideos.size();
			delete plasmideos[i];
			plasmideos[i] = new_plasmideo;
		}
	} else {
		delete new_plasmideo;
	}
}

void TransgeneticAlgorithm::checkBest() {
	for (int i = 0; i < n; ++i) {
		if (population[i]->assessFitness() > quality_best) 
			quality_best = population[i]->assessFitness();
	}
}

Cromossom** TransgeneticAlgorithm::initPopulation() {
	Cromossom **pop = new Cromossom*[n];
	
	for (int i = 0; i < n; ++i) {
		pop[i] = new Cromossom(k,L,sets);
	}
	
	return pop;
}

void TransgeneticAlgorithm::deletePopulation(Cromossom** p) {
	for(int i = 0; i < n; ++i)
		delete population[i];
	delete [] population;
}

void TransgeneticAlgorithm::copySolution(int* s1, int* s2) {
	for( int i = 0; i < k; ++i )
		s1[i] = s2[i];
}

int TransgeneticAlgorithm::getQualityOfBest() {
	return quality_best;
}

